﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace LitTools
{
    public abstract class BasePool<T>
    {
        /// <summary>
        /// 数量上限
        /// </summary>
        public int maxSize = 100;
        /// <summary>
        /// 所有实例列表
        /// </summary>
        private List<T> allItems;
        /// <summary>
        /// 回收的实例列表
        /// </summary>
        private List<T> recycleItems;

        #region 抽象方法

        /// <summary>
        /// 创建实例
        /// </summary>
        /// <returns></returns>
        protected abstract T CreateObject(params object[] args);
        /// <summary>
        /// 租借实例前
        /// </summary>
        /// <param name="instance"></param>
        protected virtual void OnRent(T instance, params object[] args) { }
        /// <summary>
        /// 回收实例前
        /// </summary>
        /// <param name="instance"></param>
        protected virtual void OnRecycle(T instance) { }
        /// <summary>
        /// 释放实例前
        /// </summary>
        /// <param name="instance"></param>
        protected virtual void OnRelease(T instance) { }

        #endregion

        #region 公有方法

        /// <summary>
        /// 租借实例
        /// </summary>
        /// <returns></returns>
        public T RentObject(params object[] args)
        {
            T instance;
            if (recycleItems == null
                || recycleItems.Count == 0)
            {
                instance = CreateObject(args);
                allItems ??= new List<T>();
                allItems.Add(instance);
            }
            else
            {
                instance = recycleItems[0];
                OnRent(instance, args);
                recycleItems.RemoveAt(0);
            }
            return instance;
        }

        /// <summary>
        /// 回收实例
        /// </summary>
        /// <param name="instance"></param>
        public void RecycleObject(T instance)
        {
            if (instance == null) return;
            if (allItems.Count > maxSize)
            {
                //直接释放
                allItems.Remove(instance);
                if (recycleItems != null && recycleItems.Contains(instance))
                    recycleItems.Remove(instance);
                OnRelease(instance);
            }
            else
            {
                //放入回收池
                recycleItems ??= new List<T>();
                recycleItems.Add(instance);
                OnRecycle(instance);
            }
        }

        /// <summary>
        /// 回收所有实例
        /// </summary>
        public void RecycleAll()
        {
            for (int i = 0; i < allItems.Count - maxSize; i++)
            {
                //直接释放
                var instance = allItems[i];
                allItems.Remove(instance);
                if (recycleItems != null && recycleItems.Contains(instance))
                    recycleItems.Remove(instance);
                OnRelease(instance);
                i--;
            }
            for (int i = 0; i < allItems.Count; i++)
            {
                //放入回收池
                var instance = allItems[i];
                recycleItems ??= new List<T>();
                recycleItems.Add(instance);
                OnRecycle(instance);
            }
        }

        /// <summary>
        /// 释放实例
        /// </summary>
        /// <param name="instance"></param>
        public void ReleaseObject(T instance)
        {
            if (allItems != null && allItems.Contains(instance))
            {
                allItems.Remove(instance);
            }
            if (recycleItems != null && recycleItems.Contains(instance))
            {
                recycleItems.Remove(instance);
            }
            OnRelease(instance);
        }

        /// <summary>
        /// 清理对象池
        /// </summary>
        public void ReleaseAll()
        {
            if (allItems != null && allItems.Count > 0)
            {
                for (int i = 0; i < allItems.Count; i++)
                {
                    OnRelease(allItems[i]);
                }
                allItems.Clear();
            }
            if (recycleItems != null && recycleItems.Count > 0)
            {
                recycleItems.Clear();
            }
        }

        #endregion
    }
}